/**
 * @description redis 缓存工厂类
 */
const RedisClient = require('ioredis');
const path = require('path');

const env = process.env.NODE_ENV || 'development';
const RedisConfig = require(path.join(__dirname, '../config/config.json'))[env].redis;
// console.log(RedisConfig)

class CacheFactory {
  constructor() {
    this.client = RedisClient.createClient({
      host: RedisConfig.host,
      port: RedisConfig.port,
      password: RedisConfig.password,
      db: RedisConfig.db
    });
  }

  /**
   * 懒汉单例模式
   * @returns {CacheFactory}
   */
  static getInstance() {
    if (!CacheFactory.instance) {
      CacheFactory.instance = new CacheFactory();
    }
    return CacheFactory.instance;
  }

  /**
   * 获取缓存客户端
   *
   * @returns {*}
   */
  getClient() {
    return this.client;
  }

  /**
   * 获取缓存
   *
   * @param key 键值
   *
   * @returns {*}
   */
  get(key) {
    return this.client.get(key);
  }

  /**
   * 删除缓存
   *
   * @param key 键值
   *
   * @returns {*}
   */
  del(key) {
    return this.client.del(key);
  }

  /**
   * 存 只有在 key 不存在时设置 key 的值并返回1,反之返回0
   * @param key 键值
   * @param value 存入的值
   * @param expire 失效时间，单位秒
   * @returns {Promise}
   */
  setNx(key, value, expire) {
    return this.client.set(key, value, 'EX', expire, 'NX');
  }

  /**
   * 普通存 key 不存在时新增 key 存在时替换
   * @param key 键值
   * @param value 存入的值
   * @param expire 失效时间，单位秒
   * @returns {Promise}
   */
  set(key, value, expire) {
    if (!expire) {
      return this.client.set(key, value);
    }
    return this.client.set(key, value, 'EX', expire);
  }

  /**
   * list key获取
   * @param key
   */
  hgetall(key) {
    return this.client.hgetall(key);
  }

  /**
   * 自增
   * @param key
   * @param expire 失效时间，单位秒
   */
  async incr(key, expire) {
    const count = await this.client.incr(key);
    if (expire) await this.client.expire(key, expire);
    return count;
  }

  async incrBy(key, num, expire) {
    const count = await this.client.incrby(key, num);
    if (expire) await this.client.expire(key, expire);
    return count;
  }

  /**
   * 递减操作
   * @param key
   * @param expire 失效时间，单位秒
   */
  async decr(key, expire) {
    const count = await this.client.decr(key);
    if (expire) await this.client.expire(key, expire);
    return count;
  }

  /**
   * 设置失效时间
   * @param key
   * @param expire 失效时间，单位秒
   */
  expire(key, expire) {
    return this.client.expire(key, expire);
  }

  /**
   * 头部推入队列
   * @param key
   * @param value 值
   */
  lpush(key, ...value) {
    return this.client.lpush(key, ...value);
  }

  /**
   * 尾部推入队列
   * @param key
   * @param value 值
   */
  rpush(key, ...value) {
    return this.client.rpush(key, ...value);
  }

  /**
   * 头部出队列
   * @param key
   */
  lpop(key) {
    return this.client.lpop(key);
  }

  /**
   * 尾部出队列
   * @param key
   */
  rpop(key) {
    return this.client.rpop(key);
  }

  /**
   * 尾部出栈放到另外一个队列头部
   * @param source 源队列
   * @param destination 目标队列
   */
  rpoplpush(source, destination) {
    // 圆环场景
    if (!destination) source = destination;
    return this.client.rpoplpush(source, destination);
  }

  /**
   * 管道
   * @param array 指令数组
   * @returns {Array}
   */
  pipe(array) {
    return this.client.pipeline(array);
  }

  /**
   * 向集合添加一个或多个成员
   * @param key
   * @param value 值
   */
  sadd(key, ...value) {
    return this.client.sadd(key, ...value);
  }

  /**
   * 移除并返回集合中的一个随机元素
   * @param key
   */
  spop(key) {
    return this.client.spop(key);
  }

  /**
   * 判断key是否存在
   * @param key
   */
  exists(key) {
    return this.client.exists(key);
  }
}

module.exports = CacheFactory;
